﻿#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

//int& func()
//{
//	int x = 0;
//
//	return x;
//}//这个报错会说返回临时变量或临时变量的地址，引用的底层是指针来的，但是我们要用语法的角度去理解

//int main()
//{
//	int a[10];
//	//越界不一定报错
//	//a[1000] = 1;//这里赋值会报错
//	cout << a[20] << endl;//这里访问后面一点不会报错
//
//	return 0;
//}
//----------------------------------------------
//int main()
//{
//	int x;
//	x = 0;
//	int y = 1;
//
//	int& r = x;
//	// 这里将y赋值给r，r不能改变引用指向
//	r = y;
//
//	return 0;
//}
//----------------------------------------------
//引用不能把指针替代，因为引用不能改变指向。c++祖师爷最开始提出这个就只是为了解决指针的复杂场景例如二级指针，但没想过替代
//int main()
//{
//	//引用和指针涉及到权限的放大与缩小
//	int y = 0;
//	int x = 100;
//	const int* p1 = &y;//这种可以通过改变指针变量里的地址达到修改值的效果。因为只是固定解引用后的值不能变，即不能修改指向内容
//	p1 = &x;
//	cout << *p1 << endl;
//	int* const p2 = &x;//这种可以通过解引用直接修改值达到修改的效果。因为只是固定指针变量里的地址不能变
//	*p2 = 50;
//	cout << *p2 << endl;
//	return 0;
//}
//----------------------------------------------
//引用的权限问题，和指针类似，可以权限缩小和平移不能权限放大
//int main()
//{
//	int x = 0;
//	int& r1 = x;
//	x++;
//	r1 = 3;
//	cout << x << '\n';
//	//权限可以缩小
//	const int& r12 = x;
//	//r2++;//错误
//
//
//	const int y = 1;
//	// 权限不能放大
//	//int& r2 = y;//错误
//	const int& r2 = y;//权限的平移
//
//	// 权限有没有放大？没有
//	int z = y;//这个只是赋值
//
//	// 指针和引用涉及权限缩小和放大
//	const int* p1 = &y;
//	// 权限不能放大
//	//int* p2 = p1;//本来不能修改指针变量指向空间的值，你现在把地址给了可以修改的p2就会错误
//	const int* p2 = p1;
//	int* p3 = &z;//权限的平移
//	// 权限可以缩小
//	const int* p4 = p3;
//
//	return 0;
//}

//------------------------
//具体场景
//void func(const int& r)
//{
//
//}
//
//int main()
//{
//	int x = 1;
//	const int y = 2;
//	double d = 1.1;
//
//	const int& r1 = x;//缩小
//	const int& r2 = y;//平移
//	const int& r3 = 10;//因为10是常量，赋值是通过建立临时变量赋给r3，而临时变量具有常性，你不能修改，所以这里是平移
//
//	const int& r4 = x * 10;//运算结果也是常量，解释与上一个相同
//	const int& r5 = d;//类型转换的时候也是通过临时变量来弄，所以不能修改，得用const
//
//	func(x);//缩小
//	func(y);
//	func(10);
//	func(x*10);
//	func(d);
//
//	return 0;
//}

//int main()
//{
//	int x = 1;
//	int& r1 = x;
//	r1 = 2;
//
//	int* ptr = &x;
//	*ptr = 3;
//	cout << x << '\n';//3  从这里认识引用的底层
//	return 0;
//}

//-----------------------------------
//内联函数是为了解决宏的一些缺点
//#define ADD(int a, int b) return a + b;错的
//#define ADD(a, b) a + b
//#define ADD(a, b) a + b;
//#define ADD(a, b) (a + b)
#define ADD(a, b) ((a) + (b))
//#define ADD(x,y) (x)+(y)//宏没有分号
// 宏函数
// 缺点：复杂/类型安全检查/不能调试
// 优点：预处理阶段替换，不用建立栈帧，本质是一种提效。
//int main()
//{
//	int ret1 = ADD(1, 2); // int ret = (1 + 2);;
//	cout << ret1 << endl;
//
//	if (ADD(1, 2))
//	{}
//
//	int ret2 = ADD(1, 2) * 5; // int ret = (1 + 2)* 5;
//	int x = 1, y = 2;
//	cout << ret2 << endl;
//
//	ret2 = ADD(x | y, x & y); // int ret2 = (x | y + x & y);
//
//	return 0;
//}
//int main()
//{
//
//	int x = 1; int y = 2;
//	int ret = x | y;//0011
//	int r = x & y;//0000
//	cout << ret ;
//}
// 


//内联函数是为了解决宏的一些缺点  • C语言实现宏函数也会在预处理时替换展开，但是宏函数实现很复杂很容易出错的，且不⽅便调试，C++设计了inline⽬的就是替代C的宏函数。
//inline int Add(int x, int y)//太长了，代码相对多⼀些的函数，加上inline也会被编译器忽略。故不会实现像宏一样的效果，只能变成函数一样
//{
//	int ret = x + y;
//	ret += 1;
//	ret += 1;
//	ret += 1;
//	ret += 1;
//	ret += 1;
//	ret += 1;
//	ret += 1;
//	ret += 1;
//
//	return ret;
//}
//#include"F.h"
//
//int main()
//{
//	Add(1, 2);
//
//	f1(10);
//	f2(5);
//	sub(10, 5);
//	return 0;
//}

//------------------------------------------------------
//void f(int x)
//{
//	cout << "f(int x)" << endl;
//}
//void f(int* ptr)
//{
//	cout << "f(int* ptr)" << endl;
//}
//int main()
//{
//	f(0);
//	// 本想通过f(NULL)调⽤指针版本的f(int*)函数，但是由于C++中NULL被定义成0，调⽤了f(intx)，因此与程序的初衷相悖。
//	f(NULL);
//	f((int*)NULL);
//	// f((void*)NULL);	//C语言中NULL是void*// 编译报错：error C2665: “f”: 2 个重载中没有⼀个可以转换所有参数类型
//	f(nullptr);//引入这个解决类型转换的问题。，因为nullptr只能被隐式地转换为指针类型，⽽不能被转换为整数类型。
//	return 0;
//}
//--------------------------------------------------------
// 类和对象
//类名就是类型
#include"F.h"
//class Stack//class定义成员没有被访问限定符修饰时默认为private
//{
//public:
//	// 成员函数
//	void Init(int n = 4)
//	{
//		array = (int*)malloc(sizeof(int) * n);
//		if (nullptr == array)
//		{
//			perror("malloc申请空间失败");
//			return;
//		}
//		capacity = n;
//		top = 0;
//	}
//	
//	void Destroy()
//	{
//		free(array);
//		array = nullptr;
//		top = capacity = 0;
//	}
//	
//	void Push(int x)
//	{
//		// ...扩容
//		array[top++] = x;
//	}
//	
//	int Top()
//	{
//		assert(top > 0);
//		return array[top - 1];
//	}
//	
//private:
//	// 成员变量
//	int* array;
//	size_t capacity;
//	size_t top;
//};


//class Date
//{
//public:
//	void Init(int year, int month, int day)
//	{
//		_year = year;
//		_month = month;
//		_day = day;
//	}
//private:
//	 //为了区分成员变量，一般习惯上成员变量
//	 //会加一个特殊标识，如_ 或者 m开头
//	int _year; // year_ m_year
//	int _month;
//	int _day;
//};

//// C++兼容C中struct的用法
//typedef struct ListNodeC
//{
//	struct ListNodeC* next;
//	int val;
//}LTNode;
//
////C++中不再需要typedef，ListNodeCpp就可以代表类型
//struct ListNodeCpp
//{
//	ListNodeCpp* next;
//	int val;
//};
////
////C++也可以用 struct 定义类
//struct ListNodeCPP//struct定义成员没有被访问限定符修饰时默认为public
//{
//	//明显的变化是struct中可以定义函数，⼀般情况下我们还是推荐⽤class定义类。
//	void Init(int x)
//	{
//		next = nullptr;
//		val = x;
//	}
//private:
//	ListNodeCPP* next;
//	int val;
//};
//
//int main()
//{
//	Stack st;
//	st.Init();
//	st.Push(1);
//	st.Push(2);
//	st.Push(3);
//	st.Push(4);
//
//	cout << st.Top() << '\n';
//	st.Destroy();
//
//	Date date;
//	date.Init(2025, 4, 22);
//
//	struct ListNodeC* n2 = NULL;//兼容C语法
//	LTNode* n1=(LTNode*)malloc(sizeof(LTNode));//LTNode* n1;这样是不对的，因为你只是开辟了一个指针变量空间，你并没有为这个指针变量指向的LTNode开辟空间。因为最终你还是要解引用找到指向的LTNode
//	if (n1 == NULL)
//	{
//		perror("malloc");
//		exit(1);
//	}
//	n1->next = NULL;
//	n1->val = 56;
//
//
//	//C++中不再需要typedef，ListNodeCpp就可以代表类型
//	ListNodeCpp node;
//	node.next = NULL;
//	node.val = 5;
//
//	//C++独特
//	ListNodeCPP n3;
//	n3.Init(1);
//
//
//	return 0;
//}
//--------------------------------------
// 类域解决类和类之间的命名冲突
// 命名空间域 全局的函数/变量/类型的命名冲突


//int main()
//{
//	stack st;
//	st.push(1);
//
//	queue q;
//	q.push(1);
//
//	//stack::_top++;
//	stack st1;
//	st1._top++;
//	stack st2;
//	st2._top++;
//
//	return 0;
//}
//
//struct Stack1
//{
//	int size;
//
//};
//int main()
//{
//	Stack1 st;
//	st.size = 5;
//	cout << st.size << '\n';
//	return 0;
//}